package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.auth.api.UserAccountServiceFeign;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.builder.dto.ExhibitorDTO;
import com.eastfair.builder.vo.ExhibitorVO;
import com.eastfair.common.dto.AttachmentFileDTO;
import com.eastfair.common.vo.AttachmentFileVO;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.home.api.HomeViolationRecordFeign;
import com.eastfair.pay.dto.TransactionDTO;
import com.eastfair.pay.dto.TransactionOrderDTO;
import com.eastfair.pay.enumeration.TransactionOrderOrderStatusEnum;
import com.eastfair.pay.enumeration.TransactionOrderOrderTypeEnum;
import com.eastfair.pay.enums.InvoiceApplyBusinessTypeEnum;
import com.eastfair.pay.enums.TransactionStatusEnum;
import com.eastfair.pay.enums.TranstionTypeEnum;
import com.eastfair.projectcore.enumeration.MenuAffiliationEnum;
import com.eastfair.venueservice.consts.CommonConstants;
import com.eastfair.venueservice.dao.ViolationRecordMapper;
import com.eastfair.venueservice.dto.ArrangementManageDTO;
import com.eastfair.venueservice.dto.ExhibitionSettlementDTO;
import com.eastfair.venueservice.dto.ViolationRecordDTO;
import com.eastfair.venueservice.entity.*;
import com.eastfair.venueservice.enumeration.ServiceProviderTypeEnum;
import com.eastfair.venueservice.enumeration.ViolationRecordCertificateViolationTypeEnum;
import com.eastfair.venueservice.enumeration.ViolationRecordViolationSourceEnum;
import com.eastfair.venueservice.enumeration.ViolationRecordViolationStatusEnum;
import com.eastfair.venueservice.exceptioncode.VenueServiceExceptionCode;
import com.eastfair.venueservice.service.*;
import com.eastfair.venueservice.vo.ExhibitionSettlementVO;
import com.eastfair.venueservice.vo.ServiceProviderSpaceVO;
import com.eastfair.venueservice.vo.ViolationRecordVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 违规处罚记录
 * </p>
 *
 * @author lyw
 * @date 2022 -08-11
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class ViolationRecordServiceImpl extends SuperServiceImpl<ViolationRecordMapper, ViolationRecord> implements ViolationRecordService {

    /**
     * 违规记录的附件类型
     */
    public static final String VIOLATION_RECORD_BUSINESS_TYPE = "violation_record";

    private static final String VIOLATION_RECORD_FIELD = "violation_code";

    private static final int VIOLATION_RECORD_LENGTH = 5;

    @Resource
    private VenueManageAttachFileService venueManageAttachFileService;

    @Resource
    private ArrangementManageService arrangementManageService;

    @Resource
    private ExhibitionManageService exhibitionManageService;

    @Resource
    private VenueManageExhibitorService venueManageExhibitorService;

    @Resource
    private VenueManageTransactionService venueManageTransactionService;

    @Resource
    private VenueManageTransactionOrderService venueManageTransactionOrderService;

    @Resource
    private ServiceProviderService serviceProviderService;

    @Resource
    private ServiceProviderSpaceService serviceProviderSpaceService;

    @Resource
    private ViolationFineService violationFineService;

    @Resource
    private HomeBondManageService homeBondManageService;

    @Resource
    private UserAccountServiceFeign userAccountServiceFeign;

    @Resource
    private HomeViolationRecordFeign homeViolationRecordFeign;

    @Resource(name = "threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ViolationRecord> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(ViolationRecord model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        if (model.getViolationStatus() == null) {
            model.setViolationStatus(ViolationRecordViolationStatusEnum.HAS_EFFECT);
        }
        if (model.getCertificateViolationType() == null) {
            model.setCertificateViolationType(ViolationRecordCertificateViolationTypeEnum.NOT_CERTIFICATE);
        }
        return R.successDef();
    }

    @Override
    public Page<ViolationRecordVO> queryViolationRecordList(PageParams<ViolationRecordDTO> params) {
        log.info("queryViolationRecordList - 查询违规惩罚记录列表分页, params={}", params);
        // 分页查询违规记录列表
        QueryWrapper<ViolationRecord> queryWrapper = createViolationRecordVOQueryWrapper(params.getModel());
        Page<ViolationRecord> page = page(params.buildPage(), queryWrapper);
        Page<ViolationRecordVO> voPage = ConvertUtil.convertPage(page, ViolationRecordVO.class);
        List<ViolationRecordVO> list = voPage.getRecords();
        if (list == null || list.isEmpty()) {
            return voPage;
        }
        List<Long> ids = list
                .stream()
                .map(ViolationRecordVO::getId)
                .collect(Collectors.toList());
        Map<Long, List<AttachmentFileVO>> fileMap = venueManageAttachFileService.queryMapByBusinessIds(ids, VIOLATION_RECORD_BUSINESS_TYPE);
        // 查询附件
        list.forEach(violationRecordVO -> {
            List<AttachmentFileVO> attachmentFileList = fileMap.get(violationRecordVO.getId());
            violationRecordVO.setAttachmentFileVOList(attachmentFileList);
        });
        return voPage;
    }


    /**
     * 根据被监督者的id查询数据
     *
     * @param id
     * @return
     */
    @Override
    public List<ViolationRecordVO> getViolationRecordListById(Long id) {
        QueryWrapper<ViolationRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ViolationRecord::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(Objects.nonNull(id), ViolationRecord::getSupervisedId, id);
        List<ViolationRecord> list = this.list(queryWrapper);
        List<ViolationRecordVO> violationRecordVOList = ConvertUtil.convertList(list, ViolationRecordVO.class);
        return violationRecordVOList;

    }

    @Override
    public ViolationRecordVO getViolationRecord(ViolationRecordDTO violationRecordDTO) {
        log.info("getViolationRecord - 查询违规惩罚记录详情, params={}", JSONObject.toJSON(violationRecordDTO));
        QueryWrapper<ViolationRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ViolationRecord::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(ViolationRecord::getId, violationRecordDTO.getId())
                .eq(Objects.nonNull(violationRecordDTO.getSupervisorId()), ViolationRecord::getSupervisorId, violationRecordDTO.getSupervisorId())
                .eq(Objects.nonNull(violationRecordDTO.getExhibitionManageId()), ViolationRecord::getExhibitionManageId, violationRecordDTO.getExhibitionManageId())
                .eq(Objects.nonNull(violationRecordDTO.getSupervisedId()), ViolationRecord::getSupervisedId, violationRecordDTO.getSupervisedId())
        ;
        ViolationRecord violationRecord = this.getOne(queryWrapper);
        if (violationRecord == null) {
            return null;
        }
        ViolationRecordVO violationRecordVO = BeanUtil.toBean(violationRecord, ViolationRecordVO.class);
        R<String> createdByNameR = userAccountServiceFeign.getName(violationRecord.getCreatedBy());
        violationRecordVO.setCreateBy(violationRecord.getCreatedBy());
        violationRecordVO.setCreateByName(createdByNameR.getData());
        // 违规时间
        violationRecordVO.setViolationTime(violationRecord.getCreateTime());
        Long arrangeManageId = violationRecord.getArrangeManageId();
        if (arrangeManageId != null) {
            ArrangementManage arrangementManage = arrangementManageService.getById(arrangeManageId);
            if (arrangementManage != null) {
                violationRecordVO.setViolationTime(arrangementManage.getCreateTime());
            }
        }
        // 查询违规记录附件
        List<AttachmentFileVO> attachmentFileList = venueManageAttachFileService.queryByBusinessId(violationRecordVO.getId(), VIOLATION_RECORD_BUSINESS_TYPE);
        violationRecordVO.setAttachmentFileVOList(attachmentFileList);
        return violationRecordVO;
    }

    @Override
    public List<ViolationRecord> listViolationRecord(ViolationRecordDTO query) {
        QueryWrapper<ViolationRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ViolationRecord::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(query.getArrangeManageId() != null, ViolationRecord::getArrangeManageId, query.getArrangeManageId())
                .eq(query.getViolationStatus() != null, ViolationRecord::getViolationStatus, query.getViolationStatus())
                .eq(query.getExhibitorId() != null, ViolationRecord::getExhibitorId, query.getExhibitorId())
                .eq(query.getExhibitionManageId() != null, ViolationRecord::getExhibitionManageId, query.getExhibitionManageId())
                .eq(query.getSupervisedId() != null, ViolationRecord::getSupervisedId, query.getSupervisedId())
                .eq(query.getViolationSource() != null, ViolationRecord::getViolationSource, query.getViolationSource())
        ;
        return list(queryWrapper);
    }

    @Override
    public List<ViolationRecord> listByExhibitionManageId(Long exhibitionManageId, Long supervisedId) {
        ViolationRecordDTO query = new ViolationRecordDTO();
        query.setExhibitionManageId(exhibitionManageId);
        query.setSupervisedId(supervisedId);
        query.setViolationSource(ViolationRecordViolationSourceEnum.VENUE_CHECK);
        return listViolationRecord(query);
    }

    @Override
    public List<ViolationRecord> listByExhibitorId(Long exhibitorId) {
        ViolationRecordDTO query = new ViolationRecordDTO();
        query.setExhibitorId(exhibitorId);
        query.setViolationSource(ViolationRecordViolationSourceEnum.HOME_CHECK);
        return listViolationRecord(query);
    }

    @Override
    public List<ViolationRecord> listHomeCheckViolationRecordByArrangementId(Long arrangementId) {
        ViolationRecordDTO violationRecordDTO = new ViolationRecordDTO();
        violationRecordDTO.setArrangeManageId(arrangementId);
        List<ViolationRecord> list = listViolationRecord(violationRecordDTO);
        if (list == null || list.isEmpty()) {
            return list;
        }
        return list
                .stream()
                .filter(violationRecord -> !ViolationRecordViolationStatusEnum.CANCEL.eq(violationRecord.getViolationStatus())
                        && ViolationRecordViolationSourceEnum.HOME_CHECK.eq(violationRecord.getViolationSource()))
                .collect(Collectors.toList());
    }

    @Override
    public List<ViolationRecordVO> listForVenueViolationRecordSettlement(ViolationRecordDTO query) {
        log.info("listForVenueViolationRecordSettlement - 查询待结算的场馆下发的违规记录, query={}", query);
        QueryWrapper<ViolationRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ViolationRecord::getIsDeleted, BusinessConstant.DELETE_NO)
                .ne(ViolationRecord::getViolationStatus, ViolationRecordViolationStatusEnum.CANCEL)
                .eq(ViolationRecord::getViolationSource, ViolationRecordViolationSourceEnum.VENUE_CHECK)
                .eq(query.getExhibitionManageId() != null, ViolationRecord::getExhibitionManageId, query.getExhibitionManageId())
                .eq(query.getSupervisedId() != null, ViolationRecord::getSupervisedId, query.getSupervisedId())
                ;
        List<ViolationRecord> list = list(queryWrapper);
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }
        return list
                .stream()
                .map(violationRecord -> BeanUtil.toBean(violationRecord, ViolationRecordVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public ExhibitionSettlementVO getVenueViolationRecordSettlement(ExhibitionSettlementDTO query) {
        ViolationRecordDTO violationRecordQuery = new ViolationRecordDTO();
        violationRecordQuery.setExhibitionManageId(query.getExhibitionManageId());
        violationRecordQuery.setSupervisedId(query.getCompanyId());
        List<ViolationRecordVO> violationRecordList = listForVenueViolationRecordSettlement(violationRecordQuery);
        if (violationRecordList == null || violationRecordList.isEmpty()) {
            return null;
        }
        ExhibitionSettlementVO exhibitionSettlementVO = ViolationRecordService.calculateExhibitionSettlement(violationRecordList);
        return exhibitionSettlementVO;
    }

    @Override
    public List<ViolationRecordVO> listForHomeViolationRecordSettlement(ViolationRecordDTO query) {
        log.info("listForHomeViolationRecordSettlement - 查询待结算的主场下发的违规记录, query={}", query);
        QueryWrapper<ViolationRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ViolationRecord::getIsDeleted, BusinessConstant.DELETE_NO)
                .ne(ViolationRecord::getViolationStatus, ViolationRecordViolationStatusEnum.CANCEL)
                .eq(ViolationRecord::getViolationSource, ViolationRecordViolationSourceEnum.HOME_CHECK)
                .eq(query.getExhibitionManageId() != null, ViolationRecord::getExhibitionManageId, query.getExhibitionManageId())
                .eq(query.getSupervisedId() != null, ViolationRecord::getSupervisedId, query.getSupervisedId())
                .eq(StrUtil.isNotBlank(query.getSpaceCode()), ViolationRecord::getSpaceCode, query.getSpaceCode())
                .eq(StrUtil.isNotBlank(query.getSpaceName()), ViolationRecord::getSpaceName, query.getSpaceName())
                .eq(StrUtil.isNotBlank(query.getSiteCode()), ViolationRecord::getSiteCode, query.getSiteCode())
                .eq(StrUtil.isNotBlank(query.getSiteName()), ViolationRecord::getSiteName, query.getSiteName())
        ;
        List<ViolationRecord> list = list(queryWrapper);
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }
        return list
                .stream()
                .map(violationRecord -> BeanUtil.toBean(violationRecord, ViolationRecordVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public ExhibitionSettlementVO getHomeViolationRecordSettlement(ExhibitionSettlementDTO query) {
        ViolationRecordDTO violationRecordQuery = new ViolationRecordDTO();
        violationRecordQuery.setExhibitionManageId(query.getExhibitionManageId());
        violationRecordQuery.setSupervisedId(query.getCompanyId());
        violationRecordQuery.setSpaceCode(query.getSpaceCode());
        violationRecordQuery.setSpaceName(query.getSpaceName());
        violationRecordQuery.setSiteCode(query.getSiteCode());
        violationRecordQuery.setSiteName(query.getSiteName());
        List<ViolationRecordVO> violationRecordList = listForHomeViolationRecordSettlement(violationRecordQuery);
        if (violationRecordList == null || violationRecordList.isEmpty()) {
            return null;
        }
        ExhibitionSettlementVO exhibitionSettlementVO = ViolationRecordService.calculateExhibitionSettlement(violationRecordList);
        return exhibitionSettlementVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ViolationRecord saveViolationRecord(ViolationRecordDTO violationRecordDTO) {
        log.info("saveViolationRecord - 保存违规惩罚记录, violationRecordDTO={}", violationRecordDTO);
        if (StrUtil.isBlank(violationRecordDTO.getViolationCode())) {
            // 生成违规编号
            String prefix = LocalDateTimeUtil.format(LocalDate.now(), "yyyyMMdd");
            String violationCode = CreatCode.creatCode(baseMapper, VIOLATION_RECORD_FIELD, VIOLATION_RECORD_LENGTH, prefix);
            violationRecordDTO.setViolationCode(violationCode);
        }
        // 保存违规记录
        ViolationRecord violationRecord = BeanUtil.toBean(violationRecordDTO, ViolationRecord.class);
        this.save(violationRecord);
        // 更新布撤展管理记录为已处罚
        if (violationRecordDTO.getArrangeManageId() != null && ViolationRecordViolationSourceEnum.HOME_CHECK.eq(violationRecordDTO.getViolationSource())) {
            arrangementManageService.updateHasPunish(violationRecordDTO.getArrangeManageId());
        }
        int score = violationRecordDTO.getScore() == null ? 0 : -violationRecordDTO.getScore();
        if (violationRecordDTO.getSupervisedId() != null && score != 0) {
            serviceProviderService.updateCreditScore(violationRecordDTO.getSupervisedId(), score);
        }
        List<AttachmentFileDTO> attachmentFileList = violationRecordDTO.getAttachmentFileDTOs();
        if (attachmentFileList != null && !attachmentFileList.isEmpty()) {
            // 保存违规附件
            attachmentFileList.forEach(attachmentFileDTO -> {
                attachmentFileDTO.setBusinessId(violationRecord.getId());
                attachmentFileDTO.setBusinessType(VIOLATION_RECORD_BUSINESS_TYPE);
            });
            venueManageAttachFileService.saveOrUpdateAttachmentFile(attachmentFileList);
        }
        return violationRecord;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveForHome(ViolationRecordDTO violationRecordDTO) {
        log.info("saveForHome - 主场生成违规惩罚记录, violationRecordDTO={}", violationRecordDTO);
        // 保存违规记录
        violationRecordDTO.setViolationSource(ViolationRecordViolationSourceEnum.HOME_CHECK);
        ViolationRecord violationRecord = saveViolationRecord(violationRecordDTO);
        // 保存支付系统交易订单
        if (violationRecordDTO.getShouldPunishAmount() != null && !violationRecordDTO.getShouldPunishAmount().equals(BigDecimal.ZERO)) {
            saveTransactionOrder(violationRecord.getId());
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveForVenue(ViolationRecordDTO violationRecordDTO) {
        log.info("saveForVenue - 场馆巡检生成违规惩罚记录, violationRecordDTO={}", violationRecordDTO);
        ArrangementManage arrangementManage = null;
        boolean isCertificate = violationRecordDTO.getCertificateViolationType() != null && !ViolationRecordCertificateViolationTypeEnum.NOT_CERTIFICATE.eq(violationRecordDTO.getCertificateViolationType());
        // 如果处罚主体是主场或者搭建商，则需要生成布撤展管理记录给主场
        if (StrUtil.isNotBlank(violationRecordDTO.getSupervisedType())
                && (ServiceProviderTypeEnum.HOME_SERVICE_PROVIDER.eq(violationRecordDTO.getSupervisedType())
                || ServiceProviderTypeEnum.BUILD_SERVICE_PROVIDER.eq(violationRecordDTO.getSupervisedType()))) {
            CopyOptions copyOptions = CopyOptions
                    .create()
                    .setIgnoreProperties(CommonConstants.COMMON_IGNORE_PROPERTIES);
            ArrangementManageDTO arrangementManageDTO = BeanUtil.toBean(violationRecordDTO, ArrangementManageDTO.class, copyOptions);
            // 是否是扫描证件违规
            arrangementManageDTO.setIsCertificate(isCertificate);
            arrangementManage = arrangementManageService.submitForVenue(arrangementManageDTO);
        }
        // 保存违规记录
        if (arrangementManage != null) {
            violationRecordDTO.setArrangeManageId(arrangementManage.getId());
            violationRecordDTO.setConstructionPrincipal(arrangementManage.getConstructionPrincipal());
            violationRecordDTO.setPrincipalPhone(arrangementManage.getPrincipalPhone());
        }
        violationRecordDTO.setViolationSource(ViolationRecordViolationSourceEnum.VENUE_CHECK);
        ViolationRecord violationRecord;
        if (isCertificate) {
            violationRecord = saveFoVenueCheckCertificate(violationRecordDTO);
        } else {
            violationRecord = saveViolationRecord(violationRecordDTO);
        }
        // 直接扣款
        violationRecordDTO.setId(violationRecord.getId());
        violationRecordDTO.setActualPunishAmount(violationRecord.getShouldPunishAmount());
        updateVenuePunishAmount(violationRecordDTO);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ViolationRecord saveFoVenueCheckCertificate(ViolationRecordDTO violationRecordDTO) {
        log.info("saveFoVenueCheckBuilderCertificate - 场馆巡检生产证件违规惩罚记录, violationRecordDTO={}", violationRecordDTO);
        if (violationRecordDTO.getSupervisedId() == null) {
            log.error("saveFoVenueCheckBuilderCertificate - 违规企业ID为空");
            return saveViolationRecord(violationRecordDTO);
        }
        ServiceProvider serviceProvider = serviceProviderService.getById(violationRecordDTO.getSupervisedId());
        if (serviceProvider == null) {
            log.error("saveFoVenueCheckBuilderCertificate - 违规企业在系统中不存在");
            return saveViolationRecord(violationRecordDTO);
        }
        violationRecordDTO.setSupervisedId(serviceProvider.getId());
        violationRecordDTO.setSupervisedName(serviceProvider.getCompanyName());
        violationRecordDTO.setSupervisedType(serviceProvider.getServiceProviderType());
        violationRecordDTO.setSupervisedUscc(serviceProvider.getUscc());
        violationRecordDTO.setSupervisedLegalName(serviceProvider.getLegalName());
        // 主场或主运证件违规，补全展厅信息
        if (ServiceProviderTypeEnum.HOME_SERVICE_PROVIDER.eq(violationRecordDTO.getSupervisedType())
                || ServiceProviderTypeEnum.MAIN_TRANSPORT_SERVICE_PROVIDER.eq(violationRecordDTO.getSupervisedType())) {
            return saveFoVenueCheckCertificateByHomeOrTransport(violationRecordDTO);
        }
        // 搭建商证件违规，补全展厅，展位，展商信息
        if (ServiceProviderTypeEnum.BUILD_SERVICE_PROVIDER.eq(violationRecordDTO.getSupervisedType())) {
            return saveFoVenueCheckCertificateByBuilder(violationRecordDTO);
        }
        return saveViolationRecord(violationRecordDTO);
    }

    private ViolationRecord saveFoVenueCheckCertificateByHomeOrTransport(ViolationRecordDTO violationRecordDTO) {
        String spaceCode = violationRecordDTO.getSpaceCode();
        if (StrUtil.isBlank(spaceCode)) {
            log.error("saveFoVenueCheckCertificateByHomeOrTransport - 展厅编码为空");
            return saveViolationRecord(violationRecordDTO);
        }
        List<ServiceProviderSpaceVO> serviceProviderSpaceList = serviceProviderSpaceService.queryByExhibitionId(violationRecordDTO.getExhibitionManageId(), violationRecordDTO.getSupervisedId());
        if (serviceProviderSpaceList == null || serviceProviderSpaceList.isEmpty()) {
            log.error("saveFoVenueCheckCertificateByHomeOrTransport - 违规企业不存在负责的展厅, exhibitionManageId={}, supervisedId={}", violationRecordDTO.getExhibitionManageId(), violationRecordDTO.getSupervisedId());
            return saveViolationRecord(violationRecordDTO);
        }
        serviceProviderSpaceList.forEach(serviceProviderSpaceVO -> {
            if (spaceCode.equals(serviceProviderSpaceVO.getSpaceCode())) {
                violationRecordDTO.setSpaceName(serviceProviderSpaceVO.getSpaceName());
            }
        });
        return saveViolationRecord(violationRecordDTO);
    }

    private ViolationRecord saveFoVenueCheckCertificateByBuilder(ViolationRecordDTO violationRecordDTO) {
        if (StrUtil.isBlank(violationRecordDTO.getSpaceCode()) || StrUtil.isBlank(violationRecordDTO.getSiteCode())) {
            log.error("saveFoVenueCheckCertificateByBuilder - 展厅或展位编码为空, spaceCode={}, siteCode={}", violationRecordDTO.getSpaceCode(), violationRecordDTO.getSiteCode());
            return saveViolationRecord(violationRecordDTO);
        }
        // 通过展会ID，搭建商ID，展厅号，展位号 查询展商展位信息
        ExhibitorDTO exhibitorDTO = new ExhibitorDTO();
        exhibitorDTO.setExhibitionManageId(violationRecordDTO.getExhibitionManageId());
        exhibitorDTO.setBuilderId(violationRecordDTO.getSupervisedId());
        exhibitorDTO.setSpaceCode(violationRecordDTO.getSpaceCode());
        exhibitorDTO.setSiteCode(violationRecordDTO.getSiteCode());
        List<ExhibitorVO> exhibitorList = venueManageExhibitorService.queryExhibitors(exhibitorDTO);
        if (exhibitorList == null || exhibitorList.isEmpty()) {
            log.error("saveFoVenueCheckCertificateByBuilder - 展商展位不存在");
            return saveViolationRecord(violationRecordDTO);
        }
        ExhibitorVO exhibitorVO = exhibitorList.get(0);
        violationRecordDTO.setExhibitorId(exhibitorVO.getId());
        violationRecordDTO.setExhibitorName(exhibitorVO.getExhibitorName());
        violationRecordDTO.setSpaceCode(exhibitorVO.getSpaceCode());
        violationRecordDTO.setSpaceName(exhibitorVO.getSpaceName());
        violationRecordDTO.setSiteCode(exhibitorVO.getSiteCode());
        violationRecordDTO.setSiteName(exhibitorVO.getSiteName());
        violationRecordDTO.setSiteType(exhibitorVO.getSiteType().getCode());
        violationRecordDTO.setSiteArea(exhibitorVO.getSiteArea());
        violationRecordDTO.setSupervisedName(exhibitorVO.getBuilderName());
        violationRecordDTO.setSupervisedType(ServiceProviderTypeEnum.BUILD_SERVICE_PROVIDER.getCode());
        return saveViolationRecord(violationRecordDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateViolationRecord(ViolationRecordDTO violationRecordDTO) {
        log.info("updateViolationRecord - 修改违规惩罚记录, violationRecordDTO={}", violationRecordDTO);
        ViolationRecord violationRecord = BeanUtil.toBean(violationRecordDTO, ViolationRecord.class);
        this.updateById(violationRecord);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateVenuePunishAmount(ViolationRecordDTO violationRecordDTO) {
        ViolationRecord violationRecord = updatePunishAmount(violationRecordDTO);
        // 保存场馆扣款记录
        violationFineService.saveByVenueViolationRecord(violationRecord);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateHomePunishAmount(ViolationRecordDTO violationRecordDTO) {
        log.info("updatePunishAmount - 更新处罚扣款, violationRecordDTO={}", violationRecordDTO);
        ViolationRecord violationRecord = updatePunishAmount(violationRecordDTO);
        // 保存主场扣款记录
        violationFineService.saveByHomeViolationRecord(violationRecord);
        return true;
    }

    @Override
    public ViolationRecord updatePunishAmount(ViolationRecordDTO violationRecordDTO) {
        ViolationRecord violationRecord = getById(violationRecordDTO.getId());
        if (violationRecord == null) {
            throw BizException.wrap(VenueServiceExceptionCode.VIOLATION_RECORD_NOT_EXIST);
        }
        violationRecord.setViolationStatus(ViolationRecordViolationStatusEnum.HAS_DEDUCT);
        violationRecord.setActualPunishAmount(violationRecordDTO.getActualPunishAmount());
        violationRecord.setPunishAmountTime(LocalDateTime.now());
        updateById(violationRecord);
        return violationRecord;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean payPunishAmount(ViolationRecordDTO violationRecordDTO) {
        log.info("payPunishAmount - 支付处罚金额, violationRecordDTO={}", violationRecordDTO);
        ViolationRecord violationRecord = getById(violationRecordDTO.getId());
        if (violationRecord == null) {
            throw BizException.wrap(VenueServiceExceptionCode.VIOLATION_RECORD_NOT_EXIST);
        }
        BigDecimal nowActualPunishAmount = violationRecordDTO.getActualPunishAmount() == null ? BigDecimal.ZERO : violationRecordDTO.getActualPunishAmount();
        if (nowActualPunishAmount == null || BigDecimal.ZERO.compareTo(nowActualPunishAmount) == 0) {
            throw BizException.wrap(VenueServiceExceptionCode.PAY_AMOUNT_CAN_NOT_BE_ZERO);
        }
        BigDecimal actualPunishAmount = violationRecord.getActualPunishAmount() == null ? BigDecimal.ZERO : violationRecord.getActualPunishAmount();
        BigDecimal shouldPunishAmount = violationRecord.getShouldPunishAmount() == null ? BigDecimal.ZERO : violationRecord.getShouldPunishAmount();
        actualPunishAmount = actualPunishAmount.add(nowActualPunishAmount);
        if (actualPunishAmount.compareTo(shouldPunishAmount) > 0) {
            throw BizException.wrap(VenueServiceExceptionCode.ACTUAL_PAY_AMOUNT_GT_SHOULD_PAY_AMOUNT);
        }
        violationRecord.setActualPunishAmount(actualPunishAmount);
        violationRecord.setPunishAmountTime(LocalDateTime.now());
        if (actualPunishAmount.compareTo(shouldPunishAmount) >= 0) {
            violationRecord.setViolationStatus(ViolationRecordViolationStatusEnum.HAS_DEDUCT);
        }
        updateById(violationRecord);
        // 生成交易记录
        return saveTransaction(violationRecord, violationRecordDTO);
    }

    @Override
    public boolean saveTransaction(ViolationRecord violationRecord, ViolationRecordDTO violationRecordDTO) {
        TransactionDTO transactionDTO = new TransactionDTO();
        transactionDTO.setExhibitionId(violationRecord.getExhibitionManageId());
        transactionDTO.setExhibitionName(violationRecordDTO.getExhibitionManageName());
        transactionDTO.setSpaceName(violationRecord.getSpaceName());
        transactionDTO.setSiteName(violationRecord.getSiteName());
        transactionDTO.setServiceProviderId(violationRecord.getSupervisedId());
        transactionDTO.setServiceProviderName(violationRecord.getSupervisedName());
        transactionDTO.setServiceProviderType(violationRecord.getSupervisedType());
        transactionDTO.setOrderType(InvoiceApplyBusinessTypeEnum.VIOLATION_PUNISH.getCode());
        transactionDTO.setOrderNum(violationRecord.getId() + "");
        transactionDTO.setOrderAmount(violationRecordDTO.getActualPunishAmount());
        transactionDTO.setOrderTime(LocalDateTime.now());
        transactionDTO.setTransactionType(TranstionTypeEnum.PAYED.getCode());
        transactionDTO.setTransactionState(TransactionStatusEnum.PAYED.getCode());
        transactionDTO.setPayer(violationRecordDTO.getPayer());
        transactionDTO.setPayType(violationRecordDTO.getPayWay());
        transactionDTO.setSystemScene(ContextUtil.getSystemScene());
        return venueManageTransactionService.save(transactionDTO);
    }

    @Override
    public boolean saveTransactionOrder(ViolationRecordDTO violationRecordDTO) {
        log.info("saveTransactionOrder - 保存支付系统交易订单, violationRecordDTO={}", violationRecordDTO);
        TransactionOrderDTO transactionOrderDTO = new TransactionOrderDTO();
        transactionOrderDTO.setExhibitionId(violationRecordDTO.getExhibitionManageId());
        ExhibitionManage exhibitionManage = exhibitionManageService.getById(violationRecordDTO.getExhibitionManageId());
        if (exhibitionManage != null) {
            transactionOrderDTO.setExhibitionName(violationRecordDTO.getExhibitionManageName());
        }
        transactionOrderDTO.setOrderType(TransactionOrderOrderTypeEnum.FINE);
        transactionOrderDTO.setOrderNum(violationRecordDTO.getId() + "");
        transactionOrderDTO.setOrderAmount(violationRecordDTO.getShouldPunishAmount());
        transactionOrderDTO.setOrderTime(violationRecordDTO.getCreateTime());
        transactionOrderDTO.setOrderStatus(TransactionOrderOrderStatusEnum.UNPAY);
        transactionOrderDTO.setPayer(violationRecordDTO.getSupervisedName());
        transactionOrderDTO.setPayee(violationRecordDTO.getPayee());
        transactionOrderDTO.setPaymentPeriods(1);
        transactionOrderDTO.setSystemCode(violationRecordDTO.getSystemCode());
        return venueManageTransactionOrderService.save(transactionOrderDTO);
    }

    @Override
    public boolean saveTransactionOrder(Long id) {
        ViolationRecord violationRecord = getById(id);
        if (violationRecord == null) {
            throw BizException.wrap(VenueServiceExceptionCode.VIOLATION_RECORD_NOT_EXIST);
        }
        ViolationRecordDTO violationRecordDTO = BeanUtil.toBean(violationRecord, ViolationRecordDTO.class);
        violationRecordDTO.setSystemCode(MenuAffiliationEnum.P_COMPOSITE_COURT.getCode());
        violationRecordDTO.setPayee(violationRecordDTO.getSupervisorName());
        try {
            saveTransactionOrder(violationRecordDTO);
        } catch (BizException e) {
            // 发送配置收款账号的站内信
            if (e.getCode() == VenueServiceExceptionCode.PAYEE_NOT_CONFIG.getCode()) {
                asyncSendConfigPayeeInnerMsg(violationRecordDTO);
                return true;
            }
            throw e;
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelHomeViolationRecord(Long id) {
        log.info("cancelViolationRecord - 撤销处罚, id={}", id);
        ViolationRecord violationRecord = getById(id);
        if (violationRecord == null) {
            throw BizException.wrap(VenueServiceExceptionCode.VIOLATION_RECORD_NOT_EXIST);
        }
        if (ViolationRecordViolationStatusEnum.CANCEL.eq(violationRecord.getViolationStatus())) {
            throw BizException.wrap(-1, "违规记录已撤销");
        }
        violationRecord.setViolationStatus(ViolationRecordViolationStatusEnum.CANCEL);
        updateById(violationRecord);
        // 更新布撤展管理记录为未处罚
        if (violationRecord.getArrangeManageId() != null) {
            arrangementManageService.updateNotPunish(violationRecord.getArrangeManageId());
        }
        // 将扣除的信用分值加回来
        int score = violationRecord.getScore() == null ? 0 : violationRecord.getScore();
        if (violationRecord.getSupervisedId() != null && score != 0) {
            serviceProviderService.updateCreditScore(violationRecord.getSupervisedId(), score);
        }
        // 取消违规扣款记录
        violationFineService.cancelByViolationRecord(violationRecord);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delViolationRecord(Long id) {
        log.info("delViolationRecord - 删除违规惩罚记录, id={}", id);
        ViolationRecord violationRecord = getById(id);
        if (violationRecord == null) {
            throw BizException.wrap(VenueServiceExceptionCode.VIOLATION_RECORD_NOT_EXIST);
        }
        List<ViolationRecord> list = new ArrayList<>();
        list.add(violationRecord);
        removeByIdsOfLogic(list);
        // 删除附件
        venueManageAttachFileService.deleteBatchByBusinessId(id);
        // 将扣除的信用分值加回来
        int score = violationRecord.getScore() == null ? 0 : violationRecord.getScore();
        if (violationRecord.getSupervisedId() != null && score != 0 && !ViolationRecordViolationStatusEnum.CANCEL.eq(violationRecord.getViolationStatus())) {
            serviceProviderService.updateCreditScore(violationRecord.getSupervisedId(), score);
        }
        // 取消违规扣款记录
        if (!ViolationRecordViolationStatusEnum.CANCEL.eq(violationRecord.getViolationStatus())) {
            violationFineService.cancelByViolationRecord(violationRecord);
        }
        return true;
    }

    @Override
    public boolean sendConfigPayeeInnerMsg(ViolationRecordDTO violationRecordDTO) {
        log.info("sendConfigPayeeInnerMsg - 发送配置收款商户的站内信, violationRecordDTO={}", violationRecordDTO);
        R<Boolean> result = homeViolationRecordFeign.sendConfigPayeeInnerMsg(violationRecordDTO);
        log.info("sendConfigPayeeInnerMsg - 发送配置收款商户的站内信完成, result={}", result);
        if (!result.getIsSuccess()) {
            throw BizException.wrap(result.getCode(), result.getMsg());
        }
        return result.getData();
    }

    @Override
    public void asyncSendConfigPayeeInnerMsg(ViolationRecordDTO violationRecordDTO) {
        log.info("asyncSendConfigPayeeInnerMsg - 异步发送配置收款商户的站内信, violationRecordDTO={}", violationRecordDTO);
        threadPoolTaskExecutor.execute(() -> sendConfigPayeeInnerMsg(violationRecordDTO));
    }

    private QueryWrapper<ViolationRecord> createViolationRecordVOQueryWrapper(ViolationRecordDTO model) {
        QueryWrapper<ViolationRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ViolationRecord::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(Objects.nonNull(model.getExhibitionManageId()), ViolationRecord::getExhibitionManageId, model.getExhibitionManageId())
                .eq(Objects.nonNull(model.getSupervisorId()), ViolationRecord::getSupervisorId, model.getSupervisorId())
                .eq(Objects.nonNull(model.getSupervisedId()), ViolationRecord::getSupervisedId, model.getSupervisedId())
                .eq(model.getSupervisorUserId() != null, ViolationRecord::getSupervisorUserId, model.getSupervisorUserId())
                .eq(StrUtil.isNotBlank(model.getSiteType()), ViolationRecord::getSiteType, model.getSiteType())
                .eq(model.getViolationStatus() != null, ViolationRecord::getViolationStatus, model.getViolationStatus())
                .eq(model.getViolationSource() != null, ViolationRecord::getViolationSource, model.getViolationSource())
                .eq(model.getCertificateViolationType() != null, ViolationRecord::getCertificateViolationType, model.getCertificateViolationType())
                .eq(model.getCertificateId() != null, ViolationRecord::getCertificateId, model.getCertificateId())
                .like(StrUtil.isNotBlank(model.getExhibitorName()), ViolationRecord::getExhibitorName, model.getExhibitorName())
                .like(StrUtil.isNotBlank(model.getSupervisedName()), ViolationRecord::getSupervisedName, model.getSupervisedName())
                .like(StrUtil.isNotBlank(model.getSiteName()), ViolationRecord::getSiteName, model.getSiteName())
                .eq(model.getViolationSource() != null, ViolationRecord::getViolationSource, model.getViolationSource())
                .in(model.getViolationSourceList() != null && !model.getViolationSourceList().isEmpty(), ViolationRecord::getViolationSource, model.getViolationSourceList())
                .and(StrUtil.isNotBlank(model.getSearchContent()), searchContentQueryWrapper -> searchContentQueryWrapper
                        .like(ViolationRecord::getSiteName, model.getSearchContent())
                        .or()
                        .like(ViolationRecord::getSupervisedName, model.getSearchContent())
                        .or()
                        .like(ViolationRecord::getConstructionPrincipal, model.getSearchContent())
                        .or()
                        .like(ViolationRecord::getPrincipalPhone, model.getSearchContent())
                )
                .and(StrUtil.isNotBlank(model.getVenueKeyword()), venueKeywordQueryWrapper -> venueKeywordQueryWrapper
                        .like(ViolationRecord::getViolationProject, model.getVenueKeyword())
                        .or()
                        .like(ViolationRecord::getSupervisedName, model.getVenueKeyword()))
        ;
        return queryWrapper;
    }
}
